package timer

import (
	"fmt"
	"time"
)

func NewKeeyAlive() (obj *KeeyAlive) {
	obj = &KeeyAlive{
		interval: time.Minute * 5,
	}
	return
}

// 保持存活
// 用于定时执行操作，更新目标时间戳或数据
// 如果更新失败，每更一分钟进行重试
type KeeyAlive struct {
	ticker     *time.Ticker
	retryTimer *time.Timer
	close      chan bool

	interval      time.Duration
	updateHandler func() (err error)
}

// 设置更新间隔，默认为5分钟
func (e *KeeyAlive) SetInterval(val time.Duration) *KeeyAlive {
	e.interval = val
	return e
}

func (e *KeeyAlive) SetUpdateHandler(val func() (err error)) {
	e.updateHandler = val
}

func (e *KeeyAlive) update() (err error) {
	if e.updateHandler != nil {
		fmt.Println("KeeyAlive.update: ", time.Now().Format(time.Layout))
		return e.updateHandler()
	}
	return
}

func (e *KeeyAlive) Run() (err error) {
	e.ticker = time.NewTicker(e.interval)
	e.retryTimer = time.NewTimer(time.Minute)
	e.retryTimer.Stop()
	e.close = make(chan bool)
	err = e.update()
	if err != nil {
		return
	}
	go func() {
		retryCount := 0
		for {
			select {
			case <-e.ticker.C:
				updateErr := e.update()
				if updateErr != nil {
					e.ticker.Stop()
					//
					retryCount = -1 // 如果更新失败，每分钟重试一次，重试3次
					e.retryTimer.Reset(time.Minute)
				}
			case <-e.retryTimer.C:
				if retryCount == 0 {
					e.retryTimer.Stop()
				} else {
					retryCount--
					updateErr := e.update()
					if updateErr != nil {
						e.retryTimer.Reset(time.Minute)
					} else {
						e.retryTimer.Stop()
						e.ticker.Reset(e.interval)
					}
				}
			case <-e.close:
				return
			}
		}
	}()
	return nil
}

func (e *KeeyAlive) Dispose() {
	e.close <- true
	e.ticker.Stop()
	e.retryTimer.Stop()
}
